#include "StdAfx.h"
#include "Triangle.h"

Triangle::Triangle(void)
{
  m_initialized  = false;
  m_x_resolution = 1;
  m_y_resolution = 1;
#ifdef GMP_USE
  mpf_set_default_prec(20);
  mpf_init(m_area);
  mpf_init(m_side);
#endif
}

Triangle::~Triangle(void)
{
#ifdef GMP_USE
  mpf_clear(m_area);
  mpf_clear(m_side);
#endif
}

Triangle::Triangle(const POINT * pa)
{
  int loop = 0;
  for(loop;loop < 3; loop++)
    this->m_points[loop] = pa[loop];
  //clockwise side settings
  //the point[0]<->point[1] give us a bottom of triangle
  //point[1]<->point[2] give us left side
  //point[2]<->point[0] give us a right
 
  triangle_side ts;
  for(loop = 1;loop < 3; loop++)
  {
    ts._p1 = m_points[loop - 1];
    ts._p2 = m_points[loop];
    ts._side = (e_triangle)(loop - 1);
    this->SetSide(ts);
  }
  ts._p1 = m_points[loop - 1];
  ts._p2 = m_points[0];
  ts._side = (e_triangle)(loop -1);
  this->SetSide(ts);
}

#ifdef GMP_USE
const mpf_t & Triangle::Area()
{
  //We have only lenght of all sides
  //So we have to use a Heron calculation
  long double field;
  mpf_t hulex;
  mpf_t side_lenght[3];
  mpf_t sub_len[3];
  int   side, i;

  mpf_init(hulex);
  
  for(i = 0; i < 3; i++)
  {
    mpf_init(sub_len[i]);
    mpf_init(side_lenght[i]);
    mpf_set(side_lenght[i], GetLength(i));
    mpf_add(hulex,hulex,side_lenght[i]);
  }
  mpf_div_ui(hulex,hulex,2);
  //Now we have a circuit of triangle
  //mpf_set_ui(side_lenght,
  for(i = 0; i < 3; i++)
  {
    mpf_sub(sub_len[i],hulex,side_lenght[i]);
    mpf_mul(hulex,hulex,sub_len[i]);
  }

  mpf_sqrt(m_area,hulex);
  field = mpf_get_d(m_area);
  return m_area;
}
#else

const long double & Triangle::Area(int x_resolution, int y_resolution)
{
  long double hulex = 0.0f;
  long double side_len[3];

  m_x_resolution = x_resolution;
  m_y_resolution = y_resolution;

  for(int i = 0; i < 3; i++)
  {
    side_len[i] = GetLength(i);
    hulex += side_len[i];
  }

  hulex = hulex / 2;

  m_area = hulex * (hulex - side_len[0]) * (hulex - side_len[1]) * (hulex - side_len[2]);

  m_area = sqrt(m_area); //The result is in inches !!!!

  return m_area;
}

#endif

float Triangle::Angle(int, int)
{
  return 0.0;
}

void Triangle::SetSide(const triangle_side & ts)
{
  switch(ts._side)
  {
  case _bottom:
    this->m_bottom = ts;
    break;
  case _left:
    this->m_left = ts;
    break;
  case _right:
    this->m_right = ts;
    break;
  }
   
}


const triangle_side & Triangle::GetSide(int side)
{
  switch((e_triangle)side)
  {
  case _bottom:
    return m_bottom;
    break;
  case _left:
    return m_left;
    break;
  case _right:
    return m_right;
    break;
  }
}



void Triangle::SetSides(const figureVertice * p)
{
  //triangle_side side;
  //int i = 0;
  
  m_bottom._side = _bottom;
  m_bottom._p1 = p[0];
  m_bottom._p2 = p[1];

  m_left._side = _left;
  m_left._p1 = p[1];
  m_left._p2 = p[2];

  m_right._side = _right;
  m_right._p1 = p[2];
  m_right._p2 = p[0];

  m_points[0] = p[0];
  m_points[1] = p[1];
  m_points[2] = p[2];
}


void Triangle::Draw(const HWND & hwnd, const POINT & shift)
{
  int r,g,b;
  int loop = 0;
  HDC hdc;
  HPEN   newpen,oldpen;
  HBRUSH newbrush,oldbrush;
  
  hdc = GetDC(hwnd);

  r = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  g = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  b = (((double)rand() / (double)(RAND_MAX + 1))) * 255;
  newpen = CreatePen(PS_SOLID,4,RGB(r,g,b));
  newbrush = CreateSolidBrush(RGB(r,g,b));

  oldpen    = (HPEN) SelectObject(hdc,newpen);
  oldbrush  = (HBRUSH) SelectObject(hdc,newbrush);

  MoveToEx(hdc, m_points[2].x - shift.x, m_points[2].y - shift.y, NULL);
  for(;loop < 3 ; loop ++)
  {
    LineTo(hdc,m_points[loop].x - shift.x, m_points[loop].y - shift.y);
  }
  
  SelectObject(hdc,oldpen);
  SelectObject(hdc,oldbrush);

  DeleteObject(newpen);
  DeleteObject(newbrush);
  ReleaseDC(hwnd, hdc);
}

#ifdef GMP_USE
mpf_t & Triangle::GetLength(int trside)
{
  POINT v1, v2;
  
  int   len = 0;
  mpf_set_d(m_side, 0.0);

  switch(trside)
  {
  case 0:
    {
      v1 = m_bottom._p1;
      v2 = m_bottom._p2;
    }break;
  case 1:
    {
      v1 = m_right._p1;
      v2 = m_right._p2;
    }break;
  case 2:
    {
      v1 = m_left._p1;
      v2 = m_left._p2;
    }break;
  }

  v1.x = max(v1.x,v2.x) - min(v1.x,v2.x);
  v1.y = max(v1.y,v2.y) - min(v1.y,v2.y);

  v1.x = pow((double)v1.x, 2);
  v1.y = pow((double)v1.y, 2);

  len = v1.x + v1.y;

  mpf_sqrt_ui(m_side, len);

  return m_side;
}
#else
long double & Triangle::GetLength(int trside)
{
  POINT       v1, v2;
  int         len = 0;
  long double xlen_inch, ylen_inch;
  
  m_side = 0.0f;

  switch(trside)
  {
  case 0:
    {
      v1 = m_bottom._p1;
      v2 = m_bottom._p2;
    }break;
  case 1:
    {
      v1 = m_right._p1;
      v2 = m_right._p2;
    }break;
  case 2:
    {
      v1 = m_left._p1;
      v2 = m_left._p2;
    }break;
  }

  xlen_inch = max(v1.x,v2.x) - min(v1.x,v2.x);  //we have to divide by x resolution to calculate the inches
  ylen_inch = max(v1.y,v2.y) - min(v1.y,v2.y);  //we have to divide by y resolution to calculate the inches

  xlen_inch = pow((long double)(xlen_inch / m_x_resolution), 2);
  ylen_inch = pow((long double)(ylen_inch / m_y_resolution), 2);

  

  m_side = sqrt(xlen_inch + ylen_inch);

  return m_side;
}
#endif